package org.aurora.remote.protocol;

import com.alibaba.fastjson.JSON;
import org.aurora.common.serialization.Byte2ObjectSerializationFactory;

import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;

public class RemoteSerializableUtil {
    public static ByteBuffer serialize(RemoteCommand remoteCommand) {
        if (remoteCommand == null) {
            return null;
        }

        int magic = RemoteCommonConstant.REQUEST_MAGIC;

        RemoteCommandType remoteCommandType = remoteCommand.getRemoteCommandType();

        int requestOrdinal = remoteCommand.getRequestOrdinal();

        int version = remoteCommand.getVersion();

        int commandCode = remoteCommand.getCommandCode();

        byte[] dataBytes = Byte2ObjectSerializationFactory.serialization(remoteCommand, remoteCommand.getSerializationType());
        int dataLen = dataBytes == null ? 0 : dataBytes.length;

        // 魔数 4 + version 4 + 请求序号 requestOrdinal 4 + 请求类型 remoteCommandType 1 + 指令 code commandCode 4 + data 长度 4 + body 数据体长度
        int len = 4 + 4 + 4 + 1 + 4 + 4 + dataLen;
        ByteBuffer byteBuffer = ByteBuffer.allocate(4 + len);

        byteBuffer.putInt(len);

        byteBuffer.putInt(magic);

        byteBuffer.putInt(version);

        byteBuffer.putInt(requestOrdinal);

        byteBuffer.put(remoteCommandType.getCode());

        byteBuffer.putInt(commandCode);

        byteBuffer.putInt(dataLen);

        if (dataLen != 0) {
            byteBuffer.put(dataBytes);
        }

        byteBuffer.flip();

        return byteBuffer;
    }

    public static RemoteCommand deSerialize(ByteBuffer byteBuffer) {
        int magic = byteBuffer.getInt();

        if (magic != RemoteCommonConstant.REQUEST_MAGIC) {
            // todo 异常类型
            throw new RuntimeException("不能识别的请求");
        }

        int version = byteBuffer.getInt();

        if (version != RemoteCommonConstant.VERSION) {
            throw new RuntimeException("版本不匹配");
        }

        int requestOrdinal = byteBuffer.getInt();
        byte remoteCommandTypeCode = byteBuffer.get();
        int commandCode = byteBuffer.getInt();

        int dataLen = byteBuffer.getInt();

        byte[] dataBytes = new byte[dataLen];
        byteBuffer.get(dataBytes);

        RemoteCommand remoteCommand = null;
        if (RemoteCommandType.REQUEST.getCode() == remoteCommandTypeCode) {
            remoteCommand = new RemoteRequest();
        } else if (RemoteCommandType.RESPONSE.getCode() == remoteCommandTypeCode) {
            remoteCommand = new RemoteResponse();
        } else {
            throw new RuntimeException("不能识别的类型");
        }

        remoteCommand.setCommandCode(commandCode);
        remoteCommand.setRequestOrdinal(requestOrdinal);

        remoteCommand.setData(dataBytes);

        return remoteCommand;
    }
}
